//===----------------------------------------------------------------------===//
//
// This source file is part of the Soto for AWS open source project
//
// Copyright (c) 2017-2022 the Soto project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Soto project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

// THIS FILE IS AUTOMATICALLY GENERATED by https://github.com/soto-project/soto-codegenerator.
// DO NOT EDIT.

import Foundation
import SotoCore

extension Finspace {
    // MARK: Enums

    public enum EnvironmentStatus: String, CustomStringConvertible, Codable, _SotoSendable {
        case created = "CREATED"
        case createRequested = "CREATE_REQUESTED"
        case creating = "CREATING"
        case deleted = "DELETED"
        case deleteRequested = "DELETE_REQUESTED"
        case deleting = "DELETING"
        case failedCreation = "FAILED_CREATION"
        case failedDeletion = "FAILED_DELETION"
        case retryDeletion = "RETRY_DELETION"
        case suspended = "SUSPENDED"
        public var description: String { return self.rawValue }
    }

    public enum FederationMode: String, CustomStringConvertible, Codable, _SotoSendable {
        case federated = "FEDERATED"
        case local = "LOCAL"
        public var description: String { return self.rawValue }
    }

    // MARK: Shapes

    public struct CreateEnvironmentRequest: AWSEncodableShape {
        /// The list of Amazon Resource Names (ARN) of the data bundles to install. Currently supported data bundle ARNs:    arn:aws:finspace:${Region}::data-bundle/capital-markets-sample - Contains sample Capital Markets datasets, categories and controlled vocabularies.    arn:aws:finspace:${Region}::data-bundle/taq (default) - Contains trades and quotes data in addition to sample Capital Markets data.
        public let dataBundles: [String]?
        /// The description of the FinSpace environment to be created.
        public let description: String?
        /// Authentication mode for the environment.    FEDERATED - Users access FinSpace through Single Sign On (SSO) via your Identity provider.    LOCAL - Users access FinSpace via email and password managed within the FinSpace environment.
        public let federationMode: FederationMode?
        /// Configuration information when authentication mode is FEDERATED.
        public let federationParameters: FederationParameters?
        /// The KMS key id to encrypt your data in the FinSpace environment.
        public let kmsKeyId: String?
        /// The name of the FinSpace environment to be created.
        public let name: String
        /// Configuration information for the superuser.
        public let superuserParameters: SuperuserParameters?
        /// Add tags to your FinSpace environment.
        public let tags: [String: String]?

        public init(dataBundles: [String]? = nil, description: String? = nil, federationMode: FederationMode? = nil, federationParameters: FederationParameters? = nil, kmsKeyId: String? = nil, name: String, superuserParameters: SuperuserParameters? = nil, tags: [String: String]? = nil) {
            self.dataBundles = dataBundles
            self.description = description
            self.federationMode = federationMode
            self.federationParameters = federationParameters
            self.kmsKeyId = kmsKeyId
            self.name = name
            self.superuserParameters = superuserParameters
            self.tags = tags
        }

        public func validate(name: String) throws {
            try self.dataBundles?.forEach {
                try validate($0, name: "dataBundles[]", parent: name, max: 2048)
                try validate($0, name: "dataBundles[]", parent: name, min: 20)
                try validate($0, name: "dataBundles[]", parent: name, pattern: "^arn:aws:finspace:[A-Za-z0-9_/.-]{0,63}:\\d*:data-bundle/[0-9A-Za-z_-]{1,128}$")
            }
            try self.validate(self.description, name: "description", parent: name, max: 1000)
            try self.validate(self.description, name: "description", parent: name, min: 1)
            try self.validate(self.description, name: "description", parent: name, pattern: "^[a-zA-Z0-9. ]{1,1000}$")
            try self.federationParameters?.validate(name: "\(name).federationParameters")
            try self.validate(self.kmsKeyId, name: "kmsKeyId", parent: name, max: 1000)
            try self.validate(self.kmsKeyId, name: "kmsKeyId", parent: name, min: 1)
            try self.validate(self.kmsKeyId, name: "kmsKeyId", parent: name, pattern: "^[a-zA-Z-0-9-:\\/]*$")
            try self.validate(self.name, name: "name", parent: name, max: 255)
            try self.validate(self.name, name: "name", parent: name, min: 1)
            try self.validate(self.name, name: "name", parent: name, pattern: "^[a-zA-Z0-9]+[a-zA-Z0-9-]*[a-zA-Z0-9]$")
            try self.superuserParameters?.validate(name: "\(name).superuserParameters")
            try self.tags?.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.key, name: "tags.key", parent: name, pattern: "^(?!aws:)[a-zA-Z+-=._:/]+$")
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, min: 1)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, pattern: "^[a-zA-Z0-9+-=._:@ ]+$")
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 50)
            try self.validate(self.tags, name: "tags", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case dataBundles
            case description
            case federationMode
            case federationParameters
            case kmsKeyId
            case name
            case superuserParameters
            case tags
        }
    }

    public struct CreateEnvironmentResponse: AWSDecodableShape {
        /// The Amazon Resource Name (ARN) of the FinSpace environment that you created.
        public let environmentArn: String?
        /// The unique identifier for FinSpace environment that you created.
        public let environmentId: String?
        /// The sign-in url for the web application of the FinSpace environment you created.
        public let environmentUrl: String?

        public init(environmentArn: String? = nil, environmentId: String? = nil, environmentUrl: String? = nil) {
            self.environmentArn = environmentArn
            self.environmentId = environmentId
            self.environmentUrl = environmentUrl
        }

        private enum CodingKeys: String, CodingKey {
            case environmentArn
            case environmentId
            case environmentUrl
        }
    }

    public struct DeleteEnvironmentRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "environmentId", location: .uri("environmentId"))
        ]

        /// The identifier for the FinSpace environment.
        public let environmentId: String

        public init(environmentId: String) {
            self.environmentId = environmentId
        }

        public func validate(name: String) throws {
            try self.validate(self.environmentId, name: "environmentId", parent: name, max: 26)
            try self.validate(self.environmentId, name: "environmentId", parent: name, min: 1)
            try self.validate(self.environmentId, name: "environmentId", parent: name, pattern: "^[a-zA-Z0-9]{1,26}$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct DeleteEnvironmentResponse: AWSDecodableShape {
        public init() {}
    }

    public struct Environment: AWSDecodableShape {
        /// The ID of the AWS account in which the FinSpace environment is created.
        public let awsAccountId: String?
        /// The AWS account ID of the dedicated service account associated with your FinSpace environment.
        public let dedicatedServiceAccountId: String?
        /// The description of the FinSpace environment.
        public let description: String?
        /// The Amazon Resource Name (ARN) of your FinSpace environment.
        public let environmentArn: String?
        /// The identifier of the FinSpace environment.
        public let environmentId: String?
        /// The sign-in url for the web application of your FinSpace environment.
        public let environmentUrl: String?
        /// The authentication mode for the environment.
        public let federationMode: FederationMode?
        /// Configuration information when authentication mode is FEDERATED.
        public let federationParameters: FederationParameters?
        /// The KMS key id used to encrypt in the FinSpace environment.
        public let kmsKeyId: String?
        /// The name of the FinSpace environment.
        public let name: String?
        /// The url of the integrated FinSpace notebook environment in your web application.
        public let sageMakerStudioDomainUrl: String?
        /// The current status of creation of the FinSpace environment.
        public let status: EnvironmentStatus?

        public init(awsAccountId: String? = nil, dedicatedServiceAccountId: String? = nil, description: String? = nil, environmentArn: String? = nil, environmentId: String? = nil, environmentUrl: String? = nil, federationMode: FederationMode? = nil, federationParameters: FederationParameters? = nil, kmsKeyId: String? = nil, name: String? = nil, sageMakerStudioDomainUrl: String? = nil, status: EnvironmentStatus? = nil) {
            self.awsAccountId = awsAccountId
            self.dedicatedServiceAccountId = dedicatedServiceAccountId
            self.description = description
            self.environmentArn = environmentArn
            self.environmentId = environmentId
            self.environmentUrl = environmentUrl
            self.federationMode = federationMode
            self.federationParameters = federationParameters
            self.kmsKeyId = kmsKeyId
            self.name = name
            self.sageMakerStudioDomainUrl = sageMakerStudioDomainUrl
            self.status = status
        }

        private enum CodingKeys: String, CodingKey {
            case awsAccountId
            case dedicatedServiceAccountId
            case description
            case environmentArn
            case environmentId
            case environmentUrl
            case federationMode
            case federationParameters
            case kmsKeyId
            case name
            case sageMakerStudioDomainUrl
            case status
        }
    }

    public struct FederationParameters: AWSEncodableShape & AWSDecodableShape {
        /// The redirect or sign-in URL that should be entered into the SAML 2.0 compliant identity provider configuration (IdP).
        public let applicationCallBackURL: String?
        /// SAML attribute name and value. The name must always be Email and the value should be set to the attribute definition in which user email is set. For example, name would be Email and value http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress. Please check your SAML 2.0 compliant identity provider (IdP) documentation for details.
        public let attributeMap: [String: String]?
        /// Name of the identity provider (IdP).
        public let federationProviderName: String?
        /// The Uniform Resource Name (URN). Also referred as Service Provider URN or Audience URI or Service Provider Entity ID.
        public let federationURN: String?
        /// SAML 2.0 Metadata document from identity provider (IdP).
        public let samlMetadataDocument: String?
        /// Provide the metadata URL from your SAML 2.0 compliant identity provider (IdP).
        public let samlMetadataURL: String?

        public init(applicationCallBackURL: String? = nil, attributeMap: [String: String]? = nil, federationProviderName: String? = nil, federationURN: String? = nil, samlMetadataDocument: String? = nil, samlMetadataURL: String? = nil) {
            self.applicationCallBackURL = applicationCallBackURL
            self.attributeMap = attributeMap
            self.federationProviderName = federationProviderName
            self.federationURN = federationURN
            self.samlMetadataDocument = samlMetadataDocument
            self.samlMetadataURL = samlMetadataURL
        }

        public func validate(name: String) throws {
            try self.validate(self.applicationCallBackURL, name: "applicationCallBackURL", parent: name, max: 1000)
            try self.validate(self.applicationCallBackURL, name: "applicationCallBackURL", parent: name, min: 1)
            try self.validate(self.applicationCallBackURL, name: "applicationCallBackURL", parent: name, pattern: "^https?://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]$")
            try self.attributeMap?.forEach {
                try validate($0.key, name: "attributeMap.key", parent: name, max: 32)
                try validate($0.key, name: "attributeMap.key", parent: name, min: 1)
                try validate($0.key, name: "attributeMap.key", parent: name, pattern: ".*")
                try validate($0.value, name: "attributeMap[\"\($0.key)\"]", parent: name, max: 1000)
                try validate($0.value, name: "attributeMap[\"\($0.key)\"]", parent: name, min: 1)
                try validate($0.value, name: "attributeMap[\"\($0.key)\"]", parent: name, pattern: "^https?://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]$")
            }
            try self.validate(self.federationProviderName, name: "federationProviderName", parent: name, max: 32)
            try self.validate(self.federationProviderName, name: "federationProviderName", parent: name, min: 1)
            try self.validate(self.federationProviderName, name: "federationProviderName", parent: name, pattern: "^[^_\\p{Z}][\\p{L}\\p{M}\\p{S}\\p{N}\\p{P}][^_\\p{Z}]+$")
            try self.validate(self.federationURN, name: "federationURN", parent: name, max: 255)
            try self.validate(self.federationURN, name: "federationURN", parent: name, min: 1)
            try self.validate(self.federationURN, name: "federationURN", parent: name, pattern: "^[A-Za-z0-9._\\-:\\/#\\+]+$")
            try self.validate(self.samlMetadataDocument, name: "samlMetadataDocument", parent: name, max: 10_000_000)
            try self.validate(self.samlMetadataDocument, name: "samlMetadataDocument", parent: name, min: 1000)
            try self.validate(self.samlMetadataDocument, name: "samlMetadataDocument", parent: name, pattern: ".*")
            try self.validate(self.samlMetadataURL, name: "samlMetadataURL", parent: name, max: 1000)
            try self.validate(self.samlMetadataURL, name: "samlMetadataURL", parent: name, min: 1)
            try self.validate(self.samlMetadataURL, name: "samlMetadataURL", parent: name, pattern: "^https?://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]$")
        }

        private enum CodingKeys: String, CodingKey {
            case applicationCallBackURL
            case attributeMap
            case federationProviderName
            case federationURN
            case samlMetadataDocument
            case samlMetadataURL
        }
    }

    public struct GetEnvironmentRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "environmentId", location: .uri("environmentId"))
        ]

        /// The identifier of the FinSpace environment.
        public let environmentId: String

        public init(environmentId: String) {
            self.environmentId = environmentId
        }

        public func validate(name: String) throws {
            try self.validate(self.environmentId, name: "environmentId", parent: name, max: 26)
            try self.validate(self.environmentId, name: "environmentId", parent: name, min: 1)
            try self.validate(self.environmentId, name: "environmentId", parent: name, pattern: "^[a-zA-Z0-9]{1,26}$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct GetEnvironmentResponse: AWSDecodableShape {
        /// The name of the FinSpace environment.
        public let environment: Environment?

        public init(environment: Environment? = nil) {
            self.environment = environment
        }

        private enum CodingKeys: String, CodingKey {
            case environment
        }
    }

    public struct ListEnvironmentsRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "maxResults", location: .querystring("maxResults")),
            AWSMemberEncoding(label: "nextToken", location: .querystring("nextToken"))
        ]

        /// The maximum number of results to return in this request.
        public let maxResults: Int?
        /// A token generated by FinSpace that specifies where to continue pagination if a previous request was truncated. To get the next set of pages, pass in the nextToken value from the response object of the previous page call.
        public let nextToken: String?

        public init(maxResults: Int? = nil, nextToken: String? = nil) {
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 100)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 0)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 1000)
            try self.validate(self.nextToken, name: "nextToken", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, pattern: ".*")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListEnvironmentsResponse: AWSDecodableShape {
        /// A list of all of your FinSpace environments.
        public let environments: [Environment]?
        /// A token that you can use in a subsequent call to retrieve the next set of results.
        public let nextToken: String?

        public init(environments: [Environment]? = nil, nextToken: String? = nil) {
            self.environments = environments
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case environments
            case nextToken
        }
    }

    public struct ListTagsForResourceRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "resourceArn", location: .uri("resourceArn"))
        ]

        /// The Amazon Resource Name of the resource.
        public let resourceArn: String

        public init(resourceArn: String) {
            self.resourceArn = resourceArn
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, max: 2048)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, min: 20)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:aws:finspace:[A-Za-z0-9_/.-]{0,63}:\\d+:environment/[0-9A-Za-z_-]{1,128}$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListTagsForResourceResponse: AWSDecodableShape {
        /// A list of all tags for a resource.
        public let tags: [String: String]?

        public init(tags: [String: String]? = nil) {
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case tags
        }
    }

    public struct SuperuserParameters: AWSEncodableShape {
        /// The email address of the superuser.
        public let emailAddress: String
        /// The first name of the superuser.
        public let firstName: String
        /// The last name of the superuser.
        public let lastName: String

        public init(emailAddress: String, firstName: String, lastName: String) {
            self.emailAddress = emailAddress
            self.firstName = firstName
            self.lastName = lastName
        }

        public func validate(name: String) throws {
            try self.validate(self.emailAddress, name: "emailAddress", parent: name, max: 128)
            try self.validate(self.emailAddress, name: "emailAddress", parent: name, min: 1)
            try self.validate(self.emailAddress, name: "emailAddress", parent: name, pattern: "^[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+[.]+[A-Za-z]+$")
            try self.validate(self.firstName, name: "firstName", parent: name, max: 50)
            try self.validate(self.firstName, name: "firstName", parent: name, min: 1)
            try self.validate(self.firstName, name: "firstName", parent: name, pattern: "^[a-zA-Z0-9]{1,50}$")
            try self.validate(self.lastName, name: "lastName", parent: name, max: 50)
            try self.validate(self.lastName, name: "lastName", parent: name, min: 1)
            try self.validate(self.lastName, name: "lastName", parent: name, pattern: "^[a-zA-Z0-9]{1,50}$")
        }

        private enum CodingKeys: String, CodingKey {
            case emailAddress
            case firstName
            case lastName
        }
    }

    public struct TagResourceRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "resourceArn", location: .uri("resourceArn"))
        ]

        /// The Amazon Resource Name (ARN) for the resource.
        public let resourceArn: String
        /// One or more tags to be assigned to the resource.
        public let tags: [String: String]

        public init(resourceArn: String, tags: [String: String]) {
            self.resourceArn = resourceArn
            self.tags = tags
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, max: 2048)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, min: 20)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:aws:finspace:[A-Za-z0-9_/.-]{0,63}:\\d+:environment/[0-9A-Za-z_-]{1,128}$")
            try self.tags.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.key, name: "tags.key", parent: name, pattern: "^(?!aws:)[a-zA-Z+-=._:/]+$")
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, min: 1)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, pattern: "^[a-zA-Z0-9+-=._:@ ]+$")
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 50)
            try self.validate(self.tags, name: "tags", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case tags
        }
    }

    public struct TagResourceResponse: AWSDecodableShape {
        public init() {}
    }

    public struct UntagResourceRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "resourceArn", location: .uri("resourceArn")),
            AWSMemberEncoding(label: "tagKeys", location: .querystring("tagKeys"))
        ]

        /// A FinSpace resource from which you want to remove a tag or tags. The value for this parameter is an Amazon Resource Name (ARN).
        public let resourceArn: String
        /// The tag keys (names) of one or more tags to be removed.
        public let tagKeys: [String]

        public init(resourceArn: String, tagKeys: [String]) {
            self.resourceArn = resourceArn
            self.tagKeys = tagKeys
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, max: 2048)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, min: 20)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:aws:finspace:[A-Za-z0-9_/.-]{0,63}:\\d+:environment/[0-9A-Za-z_-]{1,128}$")
            try self.tagKeys.forEach {
                try validate($0, name: "tagKeys[]", parent: name, max: 128)
                try validate($0, name: "tagKeys[]", parent: name, min: 1)
                try validate($0, name: "tagKeys[]", parent: name, pattern: "^(?!aws:)[a-zA-Z+-=._:/]+$")
            }
            try self.validate(self.tagKeys, name: "tagKeys", parent: name, max: 50)
            try self.validate(self.tagKeys, name: "tagKeys", parent: name, min: 1)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct UntagResourceResponse: AWSDecodableShape {
        public init() {}
    }

    public struct UpdateEnvironmentRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "environmentId", location: .uri("environmentId"))
        ]

        /// The description of the environment.
        public let description: String?
        /// The identifier of the FinSpace environment.
        public let environmentId: String
        /// Authentication mode for the environment.    FEDERATED - Users access FinSpace through Single Sign On (SSO) via your Identity provider.    LOCAL - Users access FinSpace via email and password managed within the FinSpace environment.
        public let federationMode: FederationMode?
        public let federationParameters: FederationParameters?
        /// The name of the environment.
        public let name: String?

        public init(description: String? = nil, environmentId: String, federationMode: FederationMode? = nil, federationParameters: FederationParameters? = nil, name: String? = nil) {
            self.description = description
            self.environmentId = environmentId
            self.federationMode = federationMode
            self.federationParameters = federationParameters
            self.name = name
        }

        public func validate(name: String) throws {
            try self.validate(self.description, name: "description", parent: name, max: 1000)
            try self.validate(self.description, name: "description", parent: name, min: 1)
            try self.validate(self.description, name: "description", parent: name, pattern: "^[a-zA-Z0-9. ]{1,1000}$")
            try self.validate(self.environmentId, name: "environmentId", parent: name, max: 26)
            try self.validate(self.environmentId, name: "environmentId", parent: name, min: 1)
            try self.validate(self.environmentId, name: "environmentId", parent: name, pattern: "^[a-zA-Z0-9]{1,26}$")
            try self.federationParameters?.validate(name: "\(name).federationParameters")
            try self.validate(self.name, name: "name", parent: name, max: 255)
            try self.validate(self.name, name: "name", parent: name, min: 1)
            try self.validate(self.name, name: "name", parent: name, pattern: "^[a-zA-Z0-9]+[a-zA-Z0-9-]*[a-zA-Z0-9]$")
        }

        private enum CodingKeys: String, CodingKey {
            case description
            case federationMode
            case federationParameters
            case name
        }
    }

    public struct UpdateEnvironmentResponse: AWSDecodableShape {
        /// Returns the FinSpace environment object.
        public let environment: Environment?

        public init(environment: Environment? = nil) {
            self.environment = environment
        }

        private enum CodingKeys: String, CodingKey {
            case environment
        }
    }
}

// MARK: - Errors

/// Error enum for Finspace
public struct FinspaceErrorType: AWSErrorType {
    enum Code: String {
        case accessDeniedException = "AccessDeniedException"
        case internalServerException = "InternalServerException"
        case invalidRequestException = "InvalidRequestException"
        case limitExceededException = "LimitExceededException"
        case resourceNotFoundException = "ResourceNotFoundException"
        case serviceQuotaExceededException = "ServiceQuotaExceededException"
        case throttlingException = "ThrottlingException"
        case validationException = "ValidationException"
    }

    private let error: Code
    public let context: AWSErrorContext?

    /// initialize Finspace
    public init?(errorCode: String, context: AWSErrorContext) {
        guard let error = Code(rawValue: errorCode) else { return nil }
        self.error = error
        self.context = context
    }

    internal init(_ error: Code) {
        self.error = error
        self.context = nil
    }

    /// return error code string
    public var errorCode: String { self.error.rawValue }

    /// You do not have sufficient access to perform this action.
    public static var accessDeniedException: Self { .init(.accessDeniedException) }
    /// The request processing has failed because of an unknown error, exception or failure.
    public static var internalServerException: Self { .init(.internalServerException) }
    /// The request is invalid. Something is wrong with the input to the request.
    public static var invalidRequestException: Self { .init(.invalidRequestException) }
    /// A service limit or quota is exceeded.
    public static var limitExceededException: Self { .init(.limitExceededException) }
    /// One or more resources can&#39;t be found.
    public static var resourceNotFoundException: Self { .init(.resourceNotFoundException) }
    ///  You have exceeded your service quota. To perform the requested action,  remove some of the relevant resources, or use Service Quotas to request a service quota increase.
    public static var serviceQuotaExceededException: Self { .init(.serviceQuotaExceededException) }
    /// The request was denied due to request throttling.
    public static var throttlingException: Self { .init(.throttlingException) }
    /// The input fails to satisfy the constraints specified by an AWS service.
    public static var validationException: Self { .init(.validationException) }
}

extension FinspaceErrorType: Equatable {
    public static func == (lhs: FinspaceErrorType, rhs: FinspaceErrorType) -> Bool {
        lhs.error == rhs.error
    }
}

extension FinspaceErrorType: CustomStringConvertible {
    public var description: String {
        return "\(self.error.rawValue): \(self.message ?? "")"
    }
}
